package git;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;

public class GitService {

	private static final String LOCAL_BASE_MAIN_PATH = "F:\\ai-task-publish\\trunk";

	private static final String LOCAL_BASE_RELEASE_PATH = "F:\\ai-task-publish\\release";

	private static final UsernamePasswordCredentialsProvider CREDENTIALS = new UsernamePasswordCredentialsProvider(
			"wangsx@crossdomain.cn", "1qaz2wsxE");

	private static final String REPO_FILE_PATH = "repo.txt";

	private static final String RELEASE_BRANCH_SUFFIX = ".X-RELEASE";

	private final List<String> repoUrls = Lists.newArrayList();

	public static void main(String[] args) {
		configureLogger();
		GitService service = new GitService();
		service.initRepoUrls();
		service.cloneBatchMain();
		service.cloneBatchRelease();
	}

	private static void configureLogger() {
		Logger jgitLogger = (Logger) LoggerFactory.getLogger("org.eclipse.jgit");
		jgitLogger.setLevel(Level.ERROR);
	}

	private void initRepoUrls() {
		try {
			File file = new File(this.getClass().getClassLoader().getResource(REPO_FILE_PATH).getFile());
			List<String> lines = FileUtils.readLines(file, "UTF-8");
			repoUrls.addAll(
					lines.stream().filter(StringUtils::isNotBlank).map(String::trim).collect(Collectors.toList()));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private int compareVersions(String v1, String v2) {
		String[] parts1 = v1.split("\\.");
		String[] parts2 = v2.split("\\.");

		for (int i = 0; i < Math.min(parts1.length, parts2.length); i++) {
			int part1 = Integer.parseInt(parts1[i]);
			int part2 = Integer.parseInt(parts2[i]);
			if (part1 != part2) {
				return part1 - part2;
			}
		}
		return parts1.length - parts2.length;
	}

	private String findMaxReleaseVersionBranch(String repoUrl) {
		try {
			Collection<Ref> branches = Git.lsRemoteRepository().setHeads(true).setRemote(repoUrl)
					.setCredentialsProvider(CREDENTIALS).call();

			String maxVersion = null;
			String maxBranchName = null;

			for (Ref branch : branches) {
				String branchName = branch.getName().replace("refs/heads/", "");
				if (branchName.contains(RELEASE_BRANCH_SUFFIX)) {
					String version = branchName.replace(RELEASE_BRANCH_SUFFIX, "");
					if (maxVersion == null || compareVersions(version, maxVersion) > 0) {
						maxVersion = version;
						maxBranchName = branchName;
					}
				}
			}
			return maxBranchName;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	private void cloneBatchMain() {
		cloneBatch(repoUrls, LOCAL_BASE_MAIN_PATH, null);
	}

	private void cloneBatchRelease() {
		cloneBatch(repoUrls, LOCAL_BASE_RELEASE_PATH, this::findMaxReleaseVersionBranch);
	}

	private void cloneBatch(List<String> repoUrls, String basePath, BranchSelector branchSelector) {
		for (String repoUrl : repoUrls) {
			cloneRepository(repoUrl, basePath, branchSelector);
		}
	}

	@FunctionalInterface
	private interface BranchSelector {
		String select(String repoUrl);
	}

	private void cloneRepository(String repoUrl, String basePath, BranchSelector branchSelector) {
		try {
			String repoName = extractRepoName(repoUrl);
			String branchName = branchSelector != null ? branchSelector.select(repoUrl) : null;

			if (branchName == null && branchSelector != null) {
				throw new RuntimeException("release分支不存在");
			}

			String localPath = buildLocalPath(basePath, repoName, branchName);
			File dir = new File(localPath);

			if (dir.exists()) {
				System.out.println("克隆" + (branchSelector != null ? "release" : "") + "分支已存在: " + repoUrl);
				return;
			}

			System.out.println("正在克隆仓库: " + repoUrl + " 到 " + localPath);

			Git.cloneRepository().setURI(repoUrl).setDirectory(dir).setBranch(branchName)
					.setCloneAllBranches(branchName == null).setCredentialsProvider(CREDENTIALS).call();

			System.out.println("克隆" + (branchSelector != null ? "release" : "") + "分支成功: " + repoUrl);
		} catch (Exception e) {
			System.err.println(
					"克隆" + (branchSelector != null ? "release" : "") + "分支失败: " + repoUrl + ", 错误: " + e.getMessage());
		}
	}

	private String extractRepoName(String repoUrl) {
		String repoName = repoUrl.substring(repoUrl.lastIndexOf("/") + 1);
		return repoName.replace(".git", "");
	}

	private String buildLocalPath(String basePath, String repoName, String branchName) {
		return branchName != null ? basePath + File.separator + repoName + "-" + branchName
				: basePath + File.separator + repoName;
	}
}
